package helper

import (
	"cgs-server/helper/decoder"
	"cgs-server/pkg/set"
	"io/ioutil"
	"net/http"
	"reflect"
	"strings"
	"time"
	"unicode/utf8"

	jsoniter "github.com/json-iterator/go"
	"go.mongodb.org/mongo-driver/bson/primitive"

	"cgs-server/helper/encoder"
)

// Register custom type encoder here.
func init() {
	jsoniter.RegisterTypeEncoder(reflect.TypeOf(time.Now()).String(), encoder.TimeEncoder{})
	jsoniter.RegisterTypeEncoder(reflect.TypeOf(primitive.DateTime(0)).String(), encoder.PrimitiveTimeEncoder{})
	jsoniter.RegisterTypeEncoder(
		reflect.TypeOf(primitive.NewObjectID()).String(),
		encoder.PrimitiveObjectIDEncoder{},
	)
	jsoniter.RegisterTypeEncoder(
		reflect.TypeOf(primitive.D{}).String(),
		encoder.PrimitiveDEncoder{},
	)
	jsoniter.RegisterTypeDecoder(reflect.TypeOf(time.Now()).String(), decoder.TimeDecoder{})
}

// ToJSON convert interface{} to json bytes.
func ToJSON(obj interface{}) ([]byte, error) {
	return jsoniter.Marshal(obj)
}

// FromJSON convert json bytes to interface{}.
func FromJSON(bytes []byte, result interface{}) error {
	return jsoniter.Unmarshal(bytes, result)
}

func ReadRequestBody(result interface{}, w http.ResponseWriter, r *http.Request) error {
	r.Body = http.MaxBytesReader(w, r.Body, int64(100<<20))
	s, err := ioutil.ReadAll(r.Body) //把  body 内容读入字符串 s
	if err != nil {
		return err
	}
	return FromJSON(s, result)
}

// MinifyJson 去除json字符串中的空字符
func MinifyJson(data string) string {
	data = strings.ReplaceAll(data, "\r", "")
	data = strings.ReplaceAll(data, "\n", "")
	data = strings.ReplaceAll(data, "\t", "")
	data = strings.ReplaceAll(data, "\v", "")
	data = strings.ReplaceAll(data, "\f", "")
	return data
}

var rightBracketsSet = set.NewSet(']', '}')
var correctSymbol = set.NewSet('"', '[', '{')
var spaceSet = set.NewSet('\t', '\n', '\v', '\f', '\r', ' ')

// TrimTrailingComma 去除json字符串中的末尾的逗号
func TrimTrailingComma(data []byte) []byte {
	result := make([]byte, 0, len(data))
	temp := make([]byte, 0, len(data))

	beginFlag := false
	abandonFlag := false

	for len(data) > 0 {
		r, size := utf8.DecodeRune(data)

		// 处理两个逗号之间的数据
		if beginFlag && r == ',' {
			if len(temp) > 1 {
				result = append(result, temp[:]...)
			}
			temp = temp[:0]
			beginFlag = false
		}

		if r == ',' {
			beginFlag = true
		} else if rightBracketsSet.Contains(r) {
			beginFlag = false
			abandonFlag = true
		} else if !spaceSet.Contains(r) {
			beginFlag = false
			abandonFlag = false
			temp = append(temp, data[:size]...)
		}

		if beginFlag {
			// 写入 temp
			temp = append(temp, data[:size]...)
		} else {
			// 写入 result
			if abandonFlag {
				// 弃用, 空字符也弃用了
				temp = temp[:0]
				abandonFlag = false
			}
			if len(temp) > 0 {
				result = append(result, temp[:]...)
			} else {
				result = append(result, data[:size]...)
			}
			temp = temp[:0]
		}
		data = data[size:]
	}

	temp = temp[:0]
	data = result[:]
	return data
}

// TransformType 在两种类型直接转换
func TransformType(source, target interface{}) error {
	bytesData, err := ToJSON(source)
	if err != nil {
		return err
	}
	return FromJSON(bytesData, target)
}
